%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%  Copyright by Wenliang Du.                                       %%
%%  This work is licensed under the Creative Commons                %%
%%  Attribution-NonCommercial-ShareAlike 4.0 International License. %%
%%  To view a copy of this license, visit                           %%
%%  http://creativecommons.org/licenses/by-nc-sa/4.0/.              %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\newcommand{\commonfolder}{../../common-files}

\input{\commonfolder/header}
\input{\commonfolder/copyright}


\newcommand{\formatFigs}{./Figs}


\lhead{\bfseries SEED 实验 -- 格式化字符串攻击实验}


\begin{document}

\begin{center}
{\LARGE 格式化字符串攻击实验}
\end{center}

\seedlabcopyright{2018 - 2020}



% *******************************************
% SECTION
% ******************************************* 
\section{概述}


% The \texttt{printf()} function in C is used to print out a string according to a format.  Its
% first argument is called \textit{format string}, which defines how the string should be
% formatted. Format strings use placeholders marked by the \texttt{\%} character for the
% \texttt{printf()} function to fill in data during the printing.  The use of format strings is
% not only limited to the \texttt{printf()} function; many other functions, such as
% \texttt{sprintf()}, \texttt{fprintf()}, and \texttt{scanf()}, also use format strings. Some
% programs allow users to provide the entire or part of the contents in a format string. If such
% contents are not sanitized, malicious users can use this opportunity to get the program to run
% arbitrary code. A problem like this is called \textit{format string vulnerability}.

C 语言中的 \texttt{printf()} 函数被用来根据格式打印字符串。它的
第一个参数被称为\textit{格式化字符串}，它定义了字符串应该如何被格式化。
格式化字符串使用占位符，这些占位符由\texttt{\%}字符标记，供
\texttt{printf()}函数在打印时填充数据。格式化字符串的使用
不仅限于\texttt{printf()}函数，许多其他函数，如
\texttt{sprintf()}、\texttt{fprintf()}和\texttt{scanf()}也使用格式化字符串。一些
程序允许用户提供格式化字符串的全部或部分内容。如果这些
内容未经过滤，恶意用户可以利用这个机会使程序运行
任意代码。这样的问题被称为\textit{格式化字符串漏洞}。


% The objective of this lab is for students to gain the first-hand
% experience on format string vulnerabilities by putting what they have learned 
% about the vulnerability from class into actions. 
% Students will be given a program with a format string
% vulnerability; their task is to exploit
% the vulnerability to achieve the following damage: (1) crash the 
% program, (2) read the internal memory of the program, (3) modify
% the internal memory of the program, and most severely, 
% (4) inject and execute malicious code using the victim program's privilege. 
% This lab covers the following topics:

本实验的目标是让学生通过将课堂上学到的关于漏洞的知识付诸实践，亲身体验格式化字符串漏洞。
学生将获得一个带有格式化字符串漏洞的程序,他们的任务是利用这个漏洞以实现以下目的：
(1) 使程序崩溃，(2) 读取程序的内部内存，(3) 修改
程序的内部内存，以及最严重的，(4) 使用受害者程序的权限注入并执行恶意代码。
本实验涵盖以下主题：

% \begin{itemize}[noitemsep]
% \item Format string vulnerability, and code injection
% \item Stack layout
% \item Shellcode 
% \item Reverse shell 
% \end{itemize}

\begin{itemize}[noitemsep]
    \item 格式化字符串漏洞和代码注入
    \item 栈布局
    \item Shellcode 
    \item 反向Shell 
    \end{itemize}

% \paragraph{Readings and videos.}
% Detailed coverage of the format string attack can be found in the following:

\paragraph{参考资料和视频。}
格式化字符串攻击的详细内容可以在以下资源中找到：


% \begin{itemize}
% \item Chapter 6 of the SEED Book, \seedbook
% \item Section 9 of the SEED Lecture at Udemy, \seedcsvideo
% \item The lab also involves reverse shell, which is covered in Chapter 9 of the SEED book.
% \end{itemize}

\begin{itemize}
    \item SEED书籍，\seedbook
    \item Udemy的SEED课程第9节，\seedcsvideo
    \item 实验还涉及反向Shell，这在SEED书籍中有介绍。
\end{itemize}


\paragraph{实验环境。} \seedenvironmentC

% \paragraph{Note for instructors.}
% Instructors can customize this lab by choosing values
% for \texttt{L}. See Section~\ref{sec:vulnerable_program} for details.
% Depending on the background of students and the time allocated
% for this lab, instructors can also make the
% attack on 64-bit programs optional, because it is 
% more challenging. The attacks on 32-bit programs are sufficient
% to cover the basics of the format-string attacks.

\paragraph{教师说明。}
教师可以通过选择\texttt{L}的值来定制此实验。详见第~\ref{sec:vulnerable_program}节。
根据学生的背景和分配给本实验的时间，
教师还可以将对64位程序的攻击成为可选实验，因为这个攻击很具挑战性。对32位程序的攻击足以涵盖格式化字符串攻击的基础知识。

% *******************************************
% SECTION
% *******************************************
\section{环境设置} 


% -------------------------------------------
% SUBSECTION
% -------------------------------------------
% \subsection{Turning off Countermeasure} 

% Modern operating systems uses address space
% randomization to randomize the starting address of heap and
% stack. This makes guessing the exact addresses difficult; guessing
% addresses is one of the critical steps of the format-string attack.
% To simplify the tasks in this lab, we turn off the address randomization
% using the following command: 

\subsection{关闭安全策略} 

现代操作系统使用地址空间随机化来随机化堆和栈的起始地址。
这使得猜测确切地址变得困难，而猜测地址是格式化字符串攻击的关键步骤之一。
为了简化本实验的任务，我们使用以下命令关闭地址随机化：

\begin{lstlisting}
$ sudo sysctl -w kernel.randomize_va_space=0
\end{lstlisting}


% -------------------------------------------
% SUBSECTION
% -------------------------------------------
\subsection{易受攻击的程序}
\label{sec:vulnerable_program}

% The vulnerable program used in this lab is called
% \texttt{format.c}, which can be found in the \texttt{server-code} folder.
% This program has a format-string vulnerability,
% and your job is to exploit this vulnerability.
% The code listed below has the non-essential information removed,
% so it is different from what you get from the lab setup file.

本实验中使用的易受攻击程序文件名为
\texttt{format.c}，可以在\texttt{server-code}文件夹中找到。
这个程序有一个格式化字符串漏洞，
你的任务是利用这个漏洞。
下面列出的代码去除了非必要的信息，
所以它与你从实验设置文件中得到的不一样。


\begin{lstlisting}[label=format:code, 
       caption={易受攻击的程序 \texttt{format.c} (去除了非必要信息)}]
unsigned int  target = 0x11223344;
char *secret = "A secret message\n";

void myprintf(char *msg)
{
    // 此行有一个格式化字符串漏洞
    printf(msg);
}

int main(int argc, char **argv)
{
    char buf[1500];
    int length = fread(buf, sizeof(char), 1500, stdin);
    printf("Input size: %d\n", length);

    myprintf(buf);

    return 1;
}
\end{lstlisting}

% The above program reads data from the standard input, 
% and then passes the data to \texttt{myprintf()}, 
% which calls \texttt{printf()} to print out the data. 
% The way how the input data is fed into the \texttt{printf()} function
% is unsafe, and it leads to a format-string vulnerability. 
% We will exploit this vulnerability. 
上述程序从标准输入中读取数据，
然后将数据传递给\texttt{myprintf()}，
后者调用\texttt{printf()}打印数据。
输入数据被送入\texttt{printf()}函数的方式
是不安全的，会导致格式化字符串漏洞。
我们将利用这个漏洞。

% The program will run on a server with the root privilege, and its
% standard input will be redirected to a TCP connection between the
% server and a remote user.
% Therefore, the program actually gets its data from a remote user.
% If users can exploit this vulnerability, they can cause damages.
程序将在具有root权限的服务器上运行，其
标准输入将被重定向到服务器与远程用户之间的TCP连接。
因此，程序实际上是从远程用户处获取数据的。
如果用户可以利用这个漏洞，他们可以造成损害。


% \paragraph{Compilation.} 
% We will compile the \texttt{format} program into both 32-bit and 64-bit
% binaries (for Apple Silicon machines, we only compile the program
% into 64-bit binaries). Our pre-built Ubuntu 20.04 VM is a 64-bit VM, but it
% still supports 32-bit binaries. All we need to do is to
% use the \texttt{-m32} option in the \texttt{gcc} command.
% For 32-bit compilation, we also use \texttt{-static} to generate
% a statically-linked binary, which is self-contained and not depending
% on any dynamic library, because the 32-bit dynamic libraries
% are not installed in our containers.
\paragraph{编译。} 
我们将编译\texttt{format}程序为32位和64位
二进制文件（对于Apple Silicon机器，我们只编译
成64位二进制文件）。我们预构建的Ubuntu 20.04 VM是64位VM，但它
仍然支持32位二进制文件。我们所需要做的就是
在\texttt{gcc}命令中使用\texttt{-m32}选项。
对于32位编译，我们还使用\texttt{-static}生成
静态链接的二进制文件，它是自包含的，不依赖于任何动态库，因为32位动态库
没有安装在我们的容器中。

% The compilation commands are already provided in \texttt{Makefile}. To compile
% the code, you need to type \texttt{make} to execute those commands.
% After the compilation, we need to copy the binary into
% the \texttt{fmt-containers} folder, so they can be used by the
% containers. The following commands conduct compilation and
% installation.
编译命令已在\texttt{Makefile}中提供。要编译
代码，你需要输入\texttt{make}来执行这些命令。
编译完成后，我们需要将二进制文件复制到
\texttt{fmt-containers}文件夹中，以便它们可以被
容器使用。以下命令执行编译和安装。

\begin{lstlisting}
$ make
$ make install
\end{lstlisting}


% During the compilation, you will see a
% warning message. This warning is generated by a countermeasure implemented by
% the \texttt{gcc} compiler against format string vulnerabilities. We can
% ignore this warning for now. 
在编译过程中，你将看到一个
警告消息。这个警告是由\texttt{gcc}编译器针对格式化字符串漏洞实现的防范措施，我们现在可以
忽略这个警告。

\begin{lstlisting}
format.c: In function 'myprintf':
format.c:33:5: warning: format not a string literal and no format arguments
                        [-Wformat-security]
   33 |     printf(msg);
      |     ^~~~~~
\end{lstlisting}

% It should be noted that the program needs to be compiled using 
% the \texttt{"-z execstack"} option, which allows the stack to be 
% executable. Our ultimate goal is to inject code into the 
% server program's stack, and then trigger the code. 
% Non-executable stack is a countermeasure against stack-based 
% code injection attacks, but 
% it can be defeated using the return-to-libc technique, which 
% is covered by another SEED labs. In this lab, for simplicity,
% we disable this defeat-able countermeasure. 

应该指出，程序需要使用\texttt{"-z execstack"}选项编译，这允许栈可执行。
我们的最终目标是将代码注入到服务器程序的栈中，然后触发代码。
非可执行栈是对抗基于栈的代码注入攻击的对策，但是它可以使用return-to-libc技术被破解，
这在另一个SEED实验中有详细介绍。在这个实验中，为了简单起见，我们禁用了这个可被破解的对策。

% \paragraph{For instructors.} 
% To make the lab slightly different from the one offered in the past,
% instructors can change the value for \texttt{BUF\_SIZE} by requiring
% students to compile the server code using a different \texttt{BUF\_SIZE} value.
% In \texttt{Makefile}, the \texttt{BUF\_SIZE} value is set by
% the variable \texttt{L}. Instructors should pick a value for 
% this variable based on the suggestion described in \texttt{format.c}.
\paragraph{写给教师。} 
为了使实验与过去提供的产生差异，教师可以通过要求
学生使用不同的\texttt{BUF\_SIZE}值来编译服务器代码。
在\texttt{Makefile}中，\texttt{BUF\_SIZE}值由
变量\texttt{L}设置。教师应根据\texttt{format.c}中描述的建议为
这个变量选择一个值。


% \paragraph{The Server Program.}
% In the \texttt{server-code} folder, you can find a program called \texttt{server.c}.
% This is the main entry point of the server. It listens to port \texttt{9090}.
% When it receives a TCP connection, it
% invokes the \texttt{format} program, and sets the TCP connection
% as the standard input of the \texttt{format} program. This way,
% when \texttt{format} reads data from \texttt{stdin}, it actually
% reads from the TCP connection, i.e. the data are provided by
% the user on the TCP client side. It is not necessary for
% students to read the source code of \texttt{server.c}.
\paragraph{服务器程序。}
在\texttt{server-code}文件夹中，你可以找到一个名为\texttt{server.c}的程序。
这是服务器的主要入口点。它监听端口\texttt{9090}。
当它接收到TCP连接时，它
调用\texttt{format}程序，并将TCP连接
设置为\texttt{format}程序的标准输入。这样，
当\texttt{format}从\texttt{stdin}读取数据时，它实际上
从TCP连接中读取，即数据由
TCP客户端的用户提供。学生不需要阅读\texttt{server.c}的源代码。

% We have added a little bit of randomness
% in the server program, so different students are likely to see different values
% for the memory addresses and frame pointer. The values only change
% when the container restarts, so as long as you keep the
% container running, you will see the same numbers (the numbers
% seen by different students are still different). This randomness
% is different from the address-randomization countermeasure. Its sole
% purpose is to make students' work a little bit different.
我们在服务器程序中增加了一点随机性，
所以不同的学生可能会看到不同的内存地址和栈帧指针值。
这些值只在容器重启时改变，所以只要保持容器运行，你会看到相同的数字（不同学生看到的数字仍然是不同的）。
这种随机性与地址随机化对策不同。其唯一目的是让学生的工作略有不同。

% -------------------------------------------
% SUBSECTION
% -------------------------------------------
\subsection{容器设置和命令}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\input{\commonfolder/container/setup}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%





% *******************************************
% SECTION
% *******************************************
% \section{Task 1: Crashing the Program}

% When we start the containers using the included
% \texttt{docker-compose.yml} file, two containers will be
% started, each running a vulnerable server. 
% For this task, we will use the server running on \texttt{10.9.0.5}, 
% which runs a 32-bit program with a format-string vulnerability. 
% For Apple Silicon machines, both containers are the same, and 
% they both run a 64-bit server program (students can use any one
% in this lab).
\section{任务1：使程序崩溃}

当我们使用所包含的
\texttt{docker-compose.yml}文件启动容器时，将启动两个容器，
每个容器都运行了一个易受攻击的服务器。 
对于此任务，我们将使用在\texttt{10.9.0.5}上运行的服务器， 
它运行了一个带有格式化字符串漏洞的32位程序。 
对于Apple Silicon机器，两个容器都是一样的，并且 
它们都运行一个64位服务器程序（学生可以在此实验中使用任何一个）。

% Let's first send a benign message to this server.
% We will see the following messages printed out by the target container (the
% actual messages you see may be different).
让我们先给这个服务器发送一个消息。
我们将看到目标容器打印出的以下消息（你看到的
实际消息可能不同）。
\begin{lstlisting}
$ echo hello | nc 10.9.0.5 9090
Press Ctrl+C

// 容器控制台上的打印输出
server-10.9.0.5 | Got a connection from 10.9.0.1
server-10.9.0.5 | Starting format
server-10.9.0.5 | Input buffer (address):        0xffffd2d0
server-10.9.0.5 | The secret message's address:  0x080b4008
server-10.9.0.5 | The target variable's address: 0x080e5068
server-10.9.0.5 | Input size: 6
server-10.9.0.5 | Frame Pointer inside myprintf() = 0xffffd1f8
server-10.9.0.5 | The target variable's value (before): 0x11223344
server-10.9.0.5 | hello
server-10.9.0.5 | (^_^)(^_^) Returned properly (^_^)(^_^)
server-10.9.0.5 | The target variable's value (after):  0x11223344
\end{lstlisting}
 
% The server will accept up to \texttt{1500} bytes of the data from you.
% Your main job in this lab is to construct different payloads to exploit the format-string 
% vulnerability in the server, so you can achieve the goal specified in 
% each task. If you save your payload in a file, you can send the payload
% to the server using the following command.
服务器接受最多\texttt{1500}字节的数据。
你的主要工作是构建不同的有效载荷来实现每个任务中指定的目标。
你可以将有效载荷保存在文件中，然后使用以下命令将它发送到服务器。

\begin{lstlisting}
$ cat <file> | nc 10.9.0.5 9090
Press Ctrl+C  if it does not exit.
\end{lstlisting}

% \paragraph{Task.} Your task is to provide an input to the server, such that
% when the server program tries to print out the user input in the 
% \texttt{myprintf()} function, it will crash. You can tell whether
% the \texttt{format} program has crashed or not by looking at the 
% container's printout.  If \texttt{myprintf()} returns, 
% it will print out \texttt{"Returned properly"} and a few smiley faces.
% If you don't see them, the \texttt{format} program has probably crashed.
% However, the server program will not crash; the crashed \texttt{format} program
% runs in a child process spawned by the server program. 
\paragraph{任务。}你的任务是为服务器提供输入，使得当服务器程序在
\texttt{myprintf()}函数中打印用户输入时，它会崩溃。你可以通过查看
容器的打印输出来判断
\texttt{format}程序是否崩溃。如果\texttt{myprintf()}返回， 
它会打印出\texttt{"Returned properly"}和笑脸。
如果你看不到，\texttt{format}程序可能已经崩溃了。
然而，服务器程序是不会崩溃的，崩溃的\texttt{format}程序
运行在服务器程序创建的子进程中。

% Since most of the format strings constructed in this lab can be quite long,
% it is better to use a program to do that. Inside the \texttt{attack-code} 
% directory, we have prepared a sample code called \texttt{build\_string.py}
% for people who might not be familiar with Python. It shows how to put 
% various types of data into a string. 
由于在这个实验中构建的大多数格式化字符串可能相当长，
最好使用程序来完成。在\texttt{attack-code} 
目录中，我们为可能不熟悉Python的学生准备了一份名为\texttt{build\_string.py}的示例代码。它展示了如何将
各种类型的数据放入一个字符串中。



% *******************************************
% SECTION
% *******************************************
% \section{Task 2: Printing Out the Server Program's Memory}

% The objective of this task is to get the server to print out some data 
% from its memory (we will continue to use \texttt{10.9.0.5}). 
% The data will be printed out on the server side, so
% the attacker cannot see it. Therefore, this is not a meaningful
% attack, but the technique used in this task will be essential for 
% the subsequent tasks. 
\section{任务2：打印服务器程序的内存}

本任务的目标是让服务器打印出其内存中的一些数据
（我们将继续使用\texttt{10.9.0.5}）。 
数据只是在服务器端打印出来，攻击者无法看到它。因此，这不是一个有意义的
攻击，但是在此任务中使用的技术对于
后续任务至关重要。 

% \begin{itemize} 
% \item \textbf{Task 2.A: Stack Data.}
% The goal is to print out the data on the stack.
% How many \texttt{\%x} format specifiers do you need so you can get 
% the server program to print out the first four bytes of your 
% input? You can put some unique numbers (4 bytes) 
% there, so when they are printed out, you can immediately tell. 
% This number will be essential for most of the subsequent tasks, 
% so make sure you get it right. 


% \item \textbf{Task 2.B: Heap Data} 
% There is a secret message (a string) stored in the heap area, and you can find 
% the address of this string from the server printout. 
% Your job is to print out this secret message. 
% To achieve this goal, you need to place the address (in the binary form) 
% of the secret message in the format string.

% Most computers are small-endian machines, so to store
% an address \texttt{0xAABBCCDD} (four bytes on a 32-bit machine) in memory, 
% the least significant byte \texttt{0xDD} is stored in the lower address,
% while the most significant byte \texttt{0xAA} is stored in the higher 
% address. Therefore, when we store the address in a buffer, we need to 
% save it using this order: \texttt{0xDD}, \texttt{0xCC}, \texttt{0xBB}, and 
% then \texttt{0xAA}. In Python, you can do the following:

% \begin{lstlisting}
% number  = 0xAABBCCDD
% content[0:4]  =  (number).to_bytes(4,byteorder='little')
% \end{lstlisting}
     
% \end{itemize} 
\begin{itemize} 
    \item \textbf{任务2.A：栈数据。}
    这个任务的目标是打印出栈上的数据。你的输入会被放在栈上，你需要让
    服务器打印出你输入数据的前四个字节。
    你需要使用多少个\texttt{\%x}格式说明符才能实现这个目的？
    你可以在输入数据的开始放一些特殊的数字（4字节），
    当它们被打印出来时，你就可以清楚地看到。  
    
    
    \item \textbf{任务2.B：堆数据} 
    有一个秘密消息（一个字符串）存储在堆区域，你可以从
    服务器打印输出中找到这个字符串的地址。 
    你的工作是打印出这个秘密消息。 
    为了实现这个目标，你需要在格式化字符串中放置秘密消息的地址（以二进制形式） 。
    
    大多数计算机是小端机器，所以存储
    一个地址\texttt{0xAABBCCDD}（32位机器上的四个字节）在内存中， 
    最低有效字节\texttt{0xDD}存储在较低的地址，
    最高有效字节\texttt{0xAA}存储在较高的地址。
    因此，当我们在缓冲区中存储地址时，我们需要按照这个顺序保存它：\texttt{0xDD}，\texttt{0xCC}，\texttt{0xBB}，然后 
    是\texttt{0xAA}。在Python中，你可以这样做：
    
    \begin{lstlisting}
    number  = 0xAABBCCDD
    content[0:4]  =  (number).to_bytes(4,byteorder='little')
    \end{lstlisting}
         
\end{itemize} 
    
    
    




% *******************************************
% SECTION
% *******************************************
% \section{Task 3: Modifying the Server Program's Memory}
\section{任务3：修改服务器程序的内存}

% The objective of this task is to modify the value of the 
% \texttt{target} variable that is defined in the 
% server program (we will continue to use \texttt{10.9.0.5}). 
% The original value of \texttt{target} is \texttt{0x11223344}. 
% Assume that this variable holds an important value, which can affect the 
% control flow of the program. If remote attackers can change its value, 
% they can change the behavior of this program. We have three sub-tasks. 
本任务的目标是修改
服务器程序中的\texttt{target}变量的值（我们将继续使用\texttt{10.9.0.5}）。 
\texttt{target}的原始值是\texttt{0x11223344}。 
假设这个变量保存了一个重要的值，可以影响程序的 
控制流。如果远程攻击者可以更改其值， 
他们可以改变这个程序的行为。我们有三个子任务。 

% \begin{itemize} 
% \item \textbf{Task 3.A: Change the value to a different value.}
% In this sub-task, we need to change the content of the \texttt{target} variable
% to something else. Your task is considered as a success if you can change it to a
% different value, regardless of what value it may be. The address of 
% the \texttt{target} variable can be found from the server printout. 


% \item \textbf{Task 3.B: Change the value to \texttt{0x5000}.}  
% In this sub-task, we need to change the content of the \texttt{target} variable
% to a specific value \texttt{0x5000}. Your task is considered as 
% a success only if the variable's value becomes \texttt{0x5000}. 


% \item \textbf{Task 3.C: Change the value to \texttt{0xAABBCCDD}.}  
% This sub-task is similar to the previous one, except that the target value is 
% now a large number. In a format string attack, this 
% value is the total number of characters that
% are printed out by the \texttt{printf()} function; printing out 
% this large number of characters may take hours. You need to use a faster approach. The 
% basic idea is to use \texttt{\%hn} or \texttt{\%hhn}, instead of \texttt{\%n}, so we can modify 
% a two-byte (or one-byte) memory space, instead of four bytes. Printing out
% $2^{16}$ characters does not take much time. More details 
% can be found in the SEED book.
% \end{itemize} 
\begin{itemize} 
    \item \textbf{任务3.A：将值更改为不同的值。}
    在这个子任务中，我们需要更改\texttt{target}变量
    的内容。只要你能更改它的值，无论它是什么值，你的任务就被认为是成功的。
    \texttt{target}变量的地址可以
    从服务器打印输出中找到。 
    
    
    \item \textbf{任务3.B：将值更改为\texttt{0x5000}。}  
    在这个子任务中，我们需要将\texttt{target}变量
    的内容改为一个特定值\texttt{0x5000}。你的任务只有在变量的值
    变为\texttt{0x5000}时才被认为是成功。 
    
    
    \item \textbf{任务3.C：将值更改为\texttt{0xAABBCCDD}。}  
    这个子任务与前一个相似，只是现在的目标值是一个很大的数字。在格式化字符串攻击中，这个 
    值是由\texttt{printf()}函数打印出的字符总数决定的。打印出 
    这么多的字符可能需要几个小时。你需要使用更快的方法。基本思路是
    使用\texttt{\%hn}或\texttt{\%hhn}，而不是\texttt{\%n}，这让我们可以一次修改
    两字节（或一字节）的内存空间，而不是四个字节。打印出
    $2^{16}$个字符不会花费太多时间。更多细节
    可以在SEED书籍中找到。
    \end{itemize}


% *******************************************
% SECTION
% *******************************************
% \section{Task 4: Inject Malicious Code into the Server Program}
\section{任务4：向服务器程序注入恶意代码}

% Now we are ready to go after the crown jewel of this attack, code injection. 
% We would like to inject a piece of malicious code, in its binary format, 
% into the server's memory, and then use the format string vulnerability 
% to modify the return address field of a function, so when the function returns, 
% it jumps to our injected code. 
现在我们准备去实现这次攻击的终极目标，代码注入。
我们希望能够注入一段二进制格式的恶意代码到服务器的内存中，
然后使用格式化字符串漏洞修改函数的返回地址字段。
当函数返回时，它可以跳转到我们注入的代码。

% The technique used for this task is similar to that in the previous task:
% they both modify a 4-byte number in the memory. The previous task
% modifies the \texttt{target} variable, while this task modifies the return
% address field of a function. Students need to figure out the address
% for the return-address field based on the information printed out 
% by the server. 
此任务中用的技术与前一个任务相似：
它们都修改了内存中的一个4字节数字。前一个任务
修改了\texttt{target}变量，而这个任务修改了函数的返回
地址字段。学生需要根据服务器打印出的信息计算出返回地址字段的地址。

% -------------------------------------------
% SUBSECTION
% -------------------------------------------
\subsection{理解栈布局}

\begin{figure}[htb]
\begin{center}
\includegraphics[width=0.8\textwidth]{\formatFigs/StackLayout.pdf}
\end{center}
\caption{当\texttt{printf()}在\texttt{myprintf()}内部被调用时的栈布局。}
\label{format:fig:stacklayout}
\end{figure}

% To succeed in this task, it is essential to understand the stack layout when
% the \texttt{printf()} function is invoked inside \texttt{myprintf()}. 
% Figure~\ref{format:fig:stacklayout} depicts the stack layout. 
% It should be noted that we intentionally placed a dummy stack frame between
% the \texttt{main} and \texttt{myprintf} functions, but it is not shown in the
% figure. Before working on this task, students need to
% answer the following questions (please include your answers
% in the lab report): 
要成功完成此任务，必须理解当
\texttt{printf()}函数在\texttt{myprintf()}内部被调用时的栈布局。
图~\ref{format:fig:stacklayout}描述了栈布局。
值得注意的是，我们有意在
\texttt{main}和\texttt{myprintf}函数之间放置了一个没有用的栈帧，但它没有显示在
图中。在开始这项任务之前，学生需要
回答以下问题（请在你的实验报告中写下你的答案）：

% \begin{itemize}[noitemsep]
% \item \textbf{Question 1:}  What are the memory addresses at the locations marked by
% \ding{203} and \ding{204}?

% \item \textbf{Question 2:} How many \texttt{\%x} format specifiers do we 
% need to move the format string argument pointer to \ding{204}? Remember, 
% the argument pointer starts from the location above \ding{202}. 
% \end{itemize} 
\begin{itemize}[noitemsep]
    \item \textbf{问题1：}  标记为
    \ding{203}和\ding{204}的位置的内存地址是什么？
    
    \item \textbf{问题2：} 我们
    需要多少个\texttt{\%x}格式说明符才能将格式字符串参数指针移动到\ding{204}？
    记住，参数指针从\ding{202}上方的位置开始。
\end{itemize}



% -------------------------------------------
% SUBSECTION
% -------------------------------------------
\subsection{Shellcode} 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\input{\commonfolder/guidelines/shellcode.tex}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Both 32-bit and 64-bit versions of shellcode are included in 
% the \texttt{exploit.py} inside the \texttt{attack-code} folder (for 
% Apple Silicon machines, only 64-bit shellcode is included). 
% You can use them to build your format strings. 
32位和64位版本的shellcode都在
\texttt{attack-code}文件夹中的\texttt{exploit.py}里（对于
Apple Silicon 机器，只有64位的shellcode）。
你可以使用它们来构建你的格式字符串。

% -------------------------------------------
% SUBSECTION
% -------------------------------------------
% \subsection{Your Task} 
\subsection{你的任务}


% Please construct your input, feed it to the server program, and demonstrate that you can
% successfully get the server to run your shellcode. 
% In your lab report, you need to explain
% how your format string is constructed. Please mark on Figure~\ref{format:fig:stacklayout} where 
% your malicious code is stored (please provide the concrete address). 
请构建你的输入，将其提供给服务器程序，并证明你可以
成功地让服务器运行你的shellcode。
在你的实验报告中，你需要解释
你的格式字符串是如何构建的。请在图~\ref{format:fig:stacklayout}上标记你的恶意代码存储的位置（请提供具体地址）。

% \paragraph{Getting a Reverse Shell.}
% We are not interested in running some pre-determined commands. We
% want to get a root shell on the target server, so we can
% type any command we want. Since we are on a remote machine,
% if we simply get the server to run \texttt{/bin/bash}, we won't be able to
% control the shell program. Reverse shell is a typical
% technique to solve this problem. Section~\ref{sec:guildelines} provides
% detailed instructions on how to run a reverse shell.
% Please modify the command string in your shellcode, so you can
% get a reverse shell on the target server.
% Please include screenshots and explanation in your lab report.
\paragraph{获得反向Shell。}
我们对运行一些预定的命令不感兴趣。我们
希望在目标服务器上获得root shell，这样我们就可以
输入任何我们想要的命令。由于我们在远程机器上，
如果简单地让服务器运行\texttt{/bin/bash}，我们将无法
控制该shell程序。反向Shell是解决这个问题的一个常用技术。
第~\ref{sec:guildelines}节提供了
如何运行反向Shell的详细说明。
请修改你的shellcode中的命令字符串，以便你可以
在目标服务器上获得反向Shell。
请在你的实验报告中包括截图和解释。

% *******************************************
% SECTION
% *******************************************
% \section{Task 5: Attacking the 64-bit Server Program}
\section{任务5：攻击64位服务器程序}


% \textbf{Note:} For Apple Silicon machines, Tasks 1-4 
% are already using the 64-bit server program, so this task
% is the same as Task 4 and there is no need to repeat it. 
% However, students can find useful information about 64-bit 
% machines in this section. 
\textbf{注意：}对于Apple Silicon机器，任务1-4
已经使用了64位服务器程序，所以这个任务
与任务4相同，不需要重复。
但是，学生可以在这个部分找到有关64位
机器的有用信息。

% In the previous tasks, our target servers are 32-bit
% programs. In this task, we switch to a 64-bit server
% program.  Our new target is \texttt{10.9.0.6}, which
% runs the 64-bit version of the \texttt{format} program.
% Let's first send a hello message to this server.
% We will see the following messages printed out by the target container.
在前面的任务中，我们的目标服务器是32位
程序。在这个任务中，我们攻击一个64位服务器
程序。我们的新目标是\texttt{10.9.0.6}，它
运行\texttt{format}程序的64位版本。
让我们先给这个服务器发送一个hello消息。
我们将看到目标容器打印出的以下消息。

\begin{lstlisting}
$ echo hello | nc 10.9.0.6 9090
Press Ctrl+C

// 容器控制台上的打印输出
server-10.9.0.6 | Got a connection from 10.9.0.1
server-10.9.0.6 | Starting format
server-10.9.0.6 | Input buffer (address):        0x00007fffffffe200
server-10.9.0.6 | The secret message's address:  0x0000555555556008
server-10.9.0.6 | The target variable's address: 0x0000555555558010
server-10.9.0.6 | Input size: 6
server-10.9.0.6 | Frame Pointer (inside myprintf):      0x00007fffffffe140
server-10.9.0.6 | The target variable's value (before): 0x1122334455667788
server-10.9.0.6 | hello
server-10.9.0.6 | (^_^)(^_^)  Returned from printf()  (^_^)(^_^)
server-10.9.0.6 | The target variable's value (after):  0x1122334455667788
\end{lstlisting}
 

% You can see the values of the frame pointer and buffer's address
% become 8 bytes long (instead of 4 bytes in 32-bit programs).
% Your job is to construct your payload to exploit the format-string 
% vulnerability of the server.
% You ultimate goal is to get a root shell on
% the target server. You need to use the 64-bit version of the shellcode.
你可以看到框架指针和缓冲区的地址的值
变为8字节长（而不是32位程序中的4字节）。
你的工作是构建你的有效载荷来利用服务器的格式化字符串漏洞。
你的最终目标是获得目标服务器上的root shell。
你需要使用64位版本的shellcode。

% \paragraph{Challenges caused by 64-bit Address.}
% A challenge caused by the x64 architecture is the zeros in the address.
% Although the x64 architecture
% supports 64-bit address space, only the address from
% \texttt{0x00} through \texttt{0x00007FFFFFFFFFFF} is allowed. That means for
% every address (8 bytes), the highest two bytes are always zeros.
% This causes a problem.
\paragraph{64位地址引起的挑战。}
x64架构引起的挑战是地址中的零。
尽管x64架构
支持64位地址空间，但只允许从
\texttt{0x00}到\texttt{0x00007FFFFFFFFFFFF}的地址。这意味着对于
每个地址（8字节），最高的两个字节总是零。
这导致了一个问题。

% In the attack, we need to place addresses inside the format string. For
% 32-bit programs, we can put the addresses anywhere, because there
% are no zeros inside the address. We can no longer do this
% for the 64-bit programs. If you put an address in the middle of
% your format string, when \texttt{printf()} parses the
% format string, it will stop the parsing when it sees a zero. Basically,
% anything after the first zero in a format string will not
% be considered as part of the format string.
在攻击中，我们需要在格式字符串中放置地址。对于
32位程序，我们可以将地址放在任何地方，因为里面
没有零，但对于64位程序我们不能再这样做。
如果你把一个地址放在格式字符串的中间，当\texttt{printf()}使用这个
格式字符串时，当它看到一个零时，就会停止。
所以格式字符串中的第一个零之后的任何东西都不会
被认为是格式字符串的一部分。

% The problem caused by zeros is different from that
% in the buffer overflow attack, in which,
% zeros will terminate the memory copy if \texttt{strpcy()} is used. 
% Here, we do not have memory copy in the program, 
% so we can have zeros in our input, but where to put them
% is critical. 
% There are many ways to solve this problem, and 
% we leave this to students. In the lab report, students
% should explain how they have solved this problem. 
零引起的问题与
在缓冲区溢出攻击中不同，在缓冲区溢出攻击中，
如果使用了\texttt{strpcy()}，出现零将终止内存复制。
在这里，我们没有程序中的内存复制，
所以我们的输入中可以有零，但是放在哪里
是关键的。有很多方法可以解决这个问题，在实验报告中，学生
应该解释他们是如何解决这个问题的。

% \paragraph{A userful technique: moving the argument pointer freely.}
% In a format string, we can use \texttt{\%x} to move the
% argument pointer \texttt{va\_list} to the next optional arguments.
% We can also directly move the pointer to the \texttt{k}-th optional argument.
% This is done using the format string's parameter field (in the form of
% \texttt{k\$}).
% The following code example uses \texttt{"\%3\$.20x"} to print out the value of the
% 3rd optional argument (number 3), and then uses \texttt{"\%6\$n"} to write
% a value to the 6th optional argument (the variable \texttt{var}, its
% value will become \texttt{20}). Finally,
% using \texttt{\%2\$.10x}, it moves the pointer back to the 2nd
% optional argument (number 2), and print it out. You can see,
% using this method, we can move the pointer freely back and forth.
% This technique can be quite useful to simplify the construction
% of the format string in this task.
\paragraph{一个有用的技术：自由移动参数指针。}
在格式字符串中，我们可以使用\texttt{\%x}移动
参数指针\texttt{va\_list}到下一个可选参数。
我们也可以直接将指针移动到第\texttt{k}个可选参数。
这是使用格式字符串的参数字段完成的（形式为
\texttt{k\$}）。
以下代码示例使用\texttt{"\%3\$.20x"}打印出第三个可选参数的值（数字3），
然后使用\texttt{"\%6\$n"}写入第六个可选参数（变量\texttt{var}，其值将变为\texttt{20}）。
最后，
使用\texttt{\%2\$.10x}，它将指针移回到第2个
可选参数（数字2），并打印出来。你可以看到，
使用这种方法，我们可以自由地前后移动指针。
这种技术非常有用，可以简化任务中格式字符串的构建。

\begin{lstlisting}
#include <stdio.h>
int main()
{
    int var = 1000;
    printf("%3$.20x%6$n%2$.10x\n", 1, 2, 3, 4, 5, &var);
    printf("The value in var: %d\n",var);
    return 0;
}
----- Output ------
seed@ubuntu:$ a.out
000000000000000000030000000002
The value in var: 20
\end{lstlisting}




% *******************************************
% SECTION
% *******************************************
% \section{Task 6: Fixing the Problem}

% Remember the warning message generated by the \texttt{gcc} compiler? Please explain what
% it means. Please fix the vulnerability in the server program, and recompile it. 
% Does the compiler warning go away? Do your attacks 
% still work? You only need to try one of your attacks to see whether it still
% works or not. 
\section{任务6：解决问题}

还记得\texttt{gcc}编译器生成的警告消息吗？请解释它的含义。请修复服务器程序中的漏洞，并重新编译它。
编译器警告消失了吗？你的攻击还会有效吗？
你只需要尝试你的一个攻击来看看它是否仍然有效。

% *******************************************
% SECTION
% *******************************************
\section{Guidelines on Reverse Shell}
\label{sec:guildelines}

\input{\commonfolder/guidelines/reverse_shell.tex}




% *******************************************
% SECTION
% ******************************************* 
\section{递交}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\input{\commonfolder/submission}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


\end{document}
